#pragma once
////#include "stdafx.h"
#include "Agent.h"
#include <sstream>
#include "SimulationTime.h"
#include "Link.h"
namespace org
{
	namespace spark
	{
		namespace core
		{
			using org::spark::math::SimulationTime;
			int Agent::idCounter = 0;

			void Agent::addLink(Link *link)
			{
				if (links.empty())
				{
					links = std::vector<Link*>();
					links.push_back(link);
					return;
				}

				if (std::find(links.begin(), links.end(), link) != links.end())
					return;

				links.push_back(link);
			}

			void Agent::removeLink(Link *link)
			{
				if (links.empty())
					return;
				//TO DO 
				//links.remove(link);
			}

			std::vector<Link*> Agent::getLinks()
			{

				std::vector<Link*> copy = std::vector<Link*>(links);
				return copy;
			}

			Link *Agent::getFirstConnection(Agent *a)
			{
						//		if (a == this)
						//			return null;
				if (links.empty())
					return 0;

				for (std::vector<Link*>::const_iterator link = links.begin(); link != links.end(); ++link)
				{
					if ((*link)->isConnectedTo(a))
						return *link;
				}

				return 0;
			}

// There is no native C++ template equivalent to generic constraints:
            template<typename T>
			T Agent::getFirstConnection(Agent *a, Class *linkType)
			{
						//		if (a == this)
						//			return null;
				if (links.empty())
					return 0;

				for (std::vector<Link*>::const_iterator link = links.begin(); link != links.end(); ++link)
				{
					if ((*link)->getClass() == linkType)
						if ((*link)->isConnectedTo(a))
							return static_cast<T>(link);
				}

				return 0;
			}

// There is no native C++ template equivalent to generic constraints:
template<typename T> 
			std::vector<T> Agent::getLinks(Class *type)
			{
				if (links.empty())
					return 0;

				std::vector<T> list = std::vector<T>(links.size());

				for (std::vector<Link*>::const_iterator link = links.begin(); link != links.end(); ++link)
				{
					if ((*link)->getClass() == type)
						list.push_back(static_cast<T>(link));
				}

				return list;
			}

			void Agent::setDeepSerialization(bool deepSerialization)
			{
				this->deepSerialization = deepSerialization;
			}

			bool Agent::isDead()
			{
				return dead;
			}

			Agent::Agent()
			{
				InitializeInstanceFields();
				Observer::getInstance()->addAgent(this);
			}

			Agent::Agent(int trick)
			{
				InitializeInstanceFields();
			}

			void Agent::die()
			{
				if (dead)
					return;
						//		dead = true;

				if (links.size() > 0)
				{
					for (std::vector<Link*>::const_iterator link = links.begin(); link != links.end(); ++link)
					{
						(*link)->removeEnd(this);
					}
					links.clear();
				}

				Observer::getInstance()->removeAgent(this);
			}

			void Agent::step(long long tick)
			{

			}

			void Agent::step(SimulationTime *time)
			{

			}

			

			std::string Agent::ToString()
			{
				std::stringstream ss;//create a stringstream
				ss << id;
				return this->getClass()+ss.str();
			}

			int Agent::GetHashCode()
			{
				return id;
			}

			/*void Agent::readObject(ObjectInputStream *ois) //throw(IOException, ClassNotFoundException)
			{
						//		System.out.println("Reading agent");

				ois->defaultReadObject();


				// restore the agent in the observer
				if (deepSerialization)
				{
					Observer::getInstance()->addAgentInstantly(this);
					// automatic reset
					deepSerialization = false;
				}
			}

			void Agent::writeObject(ObjectOutputStream *oos) //throw(IOException)
			{
						//		System.out.println("Writing agent");

				oos->defaultWriteObject();

				// TODO: instantly
				// remove the agent from the observer instantly
				if (deepSerialization)
				{
					die();
					// automatic reset
					deepSerialization = false;
				}
			}*/
			std::string Agent::getClass()
			{
					return typeid(this).name();
			}
			void Agent::InitializeInstanceFields()
			{
				
				id = ++idCounter;
				dead = false;
				deepSerialization = false;
				//links = 0;
			}
		}
	}
}
